#ifndef __CORE_FEATURE_IBEX__
#define __CORE_FEATURE_IBEX__
/*!
 * @file     core_feature_ibexintr.h
 * @brief    intr feature API header file for ibex core
 */

#ifdef __cplusplus
extern "C" {
#endif

#include "core_feature_base.h"


#define IBEX_EnableICache            __IBEX_EnableICache
#define IBEX_DisableICache           __IBEX_DisableICache
#define IBEX_GetEnableICache         __IBEX_GetEnableICache

#define IBEX_EnableDummyInst         __IBEX_EnableDummyInst
#define IBEX_DisableDummyInst        __IBEX_DisableDummyInst
#define IBEX_GetEnableDummyInst      __IBEX_GetEnableDummyInst
#define IBEX_SetDummyInstMask        __IBEX_SetDummyInstMask

#define IBEX_EnableIRQ               __IBEX_EnableIRQ
#define IBEX_DisableIRQ              __IBEX_DisableIRQ
#define IBEX_GetEnableIRQ            __IBEX_GetEnableIRQ

__STATIC_FORCEINLINE void __IBEX_EnableICache(void)
{
    __RV_CSR_SET(CSR_CPUCTRLSTS, CPUCTRLSTS_ICACHE_ENABLE_Msk); 
}

__STATIC_FORCEINLINE void __IBEX_DisableICache(void)
{
    __RV_CSR_CLEAR(CSR_CPUCTRLSTS, CPUCTRLSTS_ICACHE_ENABLE_Msk); 
}

__STATIC_FORCEINLINE uint32_t __IBEX_GetEnableICache(void)
{
    return ((__RV_CSR_READ(CSR_CPUCTRLSTS) & CPUCTRLSTS_ICACHE_ENABLE_Msk) >> CPUCTRLSTS_ICACHE_ENABLE_Pos);
}

__STATIC_FORCEINLINE void __IBEX_EnableDummyInst(void)
{
    __RV_CSR_SET(CSR_CPUCTRLSTS, CPUCTRLSTS_DUMMY_INSTR_EN_Msk);
}

__STATIC_FORCEINLINE void __IBEX_DisableDummyInst(void)
{
    __RV_CSR_CLEAR(CSR_CPUCTRLSTS, CPUCTRLSTS_DUMMY_INSTR_EN_Msk);
}

__STATIC_FORCEINLINE uint32_t __IBEX_GetEnableDummyInst(void)
{
    return ((__RV_CSR_READ(CSR_CPUCTRLSTS) & CPUCTRLSTS_ICACHE_ENABLE_Msk) >> CPUCTRLSTS_ICACHE_ENABLE_Pos); 
}

__STATIC_FORCEINLINE void __IBEX_SetDummyInstMask(uint32_t mask)
{
    uint32_t inst_mask = (mask << CPUCTRLSTS_DUMMY_INSTR_MASK_Pos) & CPUCTRLSTS_DUMMY_INSTR_MASK_Msk;
    __RV_CSR_CLEAR(CSR_CPUCTRLSTS, CPUCTRLSTS_DUMMY_INSTR_MASK_Msk);
    __RV_CSR_SET(CSR_CPUCTRLSTS, inst_mask);
}


__STATIC_FORCEINLINE void __IBEX_EnableIRQ(uint8_t IRQn)
{
    if  (IRQn >= 31) __NOP();
    else
         __RV_CSR_SET(CSR_MIE, (0x1UL << IRQn));

}

__STATIC_FORCEINLINE void __IBEX_DisableIRQ(uint8_t IRQn)
{
    if  (IRQn >= 31) __NOP();
    else
        __RV_CSR_CLEAR(CSR_MIE, (0x1UL << IRQn));
}

__STATIC_FORCEINLINE uint32_t __IBEX_GetEnableIRQ(uint8_t IRQn)
{
    if (IRQn == 31) return 1;
    else 
        return (__RV_CSR_READ(CSR_MIE) >> IRQn);
}

__STATIC_FORCEINLINE void __IBEX_Save_Context(void)
{
    asm ("csrr a0, mepc");
    asm ("csrr a1, mstatus");
    asm ("addi sp, sp, -8");
    asm ("sw a0, 0(sp)");
    asm ("sw a1, 4(sp)");
    __enable_irq();
}

__STATIC_FORCEINLINE void __IBEX_Restore_Context(void)
{
    __disable_irq();
    asm ("lw a0, 0(sp)");
    asm ("lw a1, 4(sp)");
    asm ("csrw mepc, a0");
    asm ("csrw mstatus, a1");
    asm ("addi sp, sp, 8");
}



#ifdef __cplusplus
}
#endif
#endif /* __CORE_FEATURE_ECLIC__ */
